package com.ld.common.aop;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.ld.common.util.LogOutUtil;
import com.ld.shieldsb.annotation.NoLog;
import com.ld.shieldsb.common.core.model.PropertiesModel;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.web.BasicService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

public class BasicAop {
    protected static final Logger log = LoggerFactory.getLogger(BasicService.class);

    protected String viewPrefix = PropertiesModel.APPLICATION.getString("spring.mvc.view.prefix"); // 视图前缀目录
    protected String viewSuffix = PropertiesModel.APPLICATION.getString("spring.mvc.view.suffix"); // 视图后缀名称
    protected Map<String, String> methodDesMap = new HashMap<>(); // 方法描述map

    /**
     * 获取注入点的相关信息
     * 
     * @Title getJoinPointInfo
     * @author 吕凯
     * @date 2019年6月10日 上午9:31:49
     * @param joinPoint
     *            void
     */
    public void getJoinPointInfo(JoinPoint joinPoint, Object ret) {
        Boolean out = LogOutUtil.isOutAop();
        if (out) {
            if (LogOutUtil.isOutAction()) {
                // AOP代理类的信息（类对象）
//        Object obj = joinPoint.getThis();
//        log.warn("代理类：" + obj);
                // 代理的目标对象（类对象，与joinPoint.getThis()相同对象）
                Object target = joinPoint.getTarget();
                // 用的最多 通知的签名
                Signature signature = joinPoint.getSignature();
                // 代理的是哪一个方法
                String signName = signature.getName();
                // AOP代理类的名字
//        String declareTypeName = signature.getDeclaringTypeName();
//        log.warn(" 代理类：" + declareTypeName);
                // AOP代理类的类（class）信息
                Class<?> declaringType = signature.getDeclaringType();
                String resourcePath = "";
                String clssSimpleName = declaringType.getSimpleName();
                String resource = declaringType.getResource(clssSimpleName + ".class").getFile();
                resourcePath = StringUtils.substringBefore(resource, "!");
                log.warn(" controller路径：{}  代理对象：{} 代理方法：{}", resourcePath, target, signName);
            }

            if (LogOutUtil.isOutAop() && ret != null && ret instanceof String) { // 配置了输出jsp 并且 返回结果是 非空 字符串
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                String retStr = ((String) ret);
                // 排除跳转重定向
                if (!retStr.contains("forward:") && !retStr.contains("redirect:")) {
                    try {

                        String resourceJsp = request.getServletContext().getResource(viewPrefix + retStr + viewSuffix).getFile();
                        log.warn(" jsp路径：{}", resourceJsp);
                    } catch (Exception e) {
                        log.warn("页面不存在" + retStr, e);
                    }
                }
            }

        }
    }

    /**
     * 获取方法的描述
     * 
     * @Title getMethodDescription
     * @author 吕凯
     * @date 2019年6月14日 上午10:38:15
     * @param joinPoint
     * @return String
     */
    public String getMethodDescription(JoinPoint joinPoint) {
        String msg;
        Signature signature = joinPoint.getSignature();
        String mehtodAllKey = signature.getDeclaringTypeName() + "." + signature.getName();
        String methodDes = methodDesMap.get(mehtodAllKey);
        if (methodDes == null) { // 没有则查询
            MethodSignature methodSignature = (MethodSignature) signature;
            Method targetMethod = methodSignature.getMethod();
            if (targetMethod.isAnnotationPresent(ApiOperation.class)) {
                // 获取方法上注解中表明的权限
                ApiOperation apiOperation = targetMethod.getAnnotation(ApiOperation.class);
                methodDes = apiOperation.value();
                Class<?> cls = signature.getDeclaringType();
                if (cls.isAnnotationPresent(Api.class)) {
                    // 获取方法上注解中表明的权限
                    Api api = cls.getAnnotation(Api.class);
                    String apiDesp = api.value();
                    if (api.tags() != null) {
                        apiDesp += String.join(",", api.tags());
                    }
                    methodDes = apiDesp + methodDes;
                }
                methodDesMap.put(mehtodAllKey, methodDes);
            }

        }
        msg = methodDes;
        return msg;
    }

    /**
     * 输出日志
     * 
     * @Title outLog
     * @author 吕凯
     * @date 2019年6月10日 上午9:51:17
     * @param msg
     *            void
     */
    public void outLog(String msg) {
        Boolean out = LogOutUtil.isOutAop();
        if (out) {
            log.warn(msg);
        }
    }

    /**
     * 是否是不记录日志的方法
     * 
     * @Title isNologMethod
     * @author 吕凯
     * @date 2019年7月17日 下午3:13:48
     * @param joinPoint
     * @return boolean
     */
    public boolean isNologMethod(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        NoLog nolog = method.getAnnotation(NoLog.class);
        if (nolog != null) {
            return true;
        }
        return false;
    }
}
